package com.behome.netty.netty_D.server;

import com.behome.netty.common.ByteConventerKit;
import com.behome.netty.common.DecodeResult;
import com.behome.netty.netty_D.bean.*;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import lombok.extern.slf4j.Slf4j;

import java.nio.ByteBuffer;
import java.util.*;

/**
 * @author bh_ljy
 * @description: 应急广播国标附录D解析器
 * @date: 2024/3/29 15:20
 */
@Slf4j
public class StandardDDecoder extends ByteToMessageDecoder {

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> list) {
        try {
            in.markReaderIndex();
            byte[] buffer = new byte[in.readableBytes()];
            in.readBytes(buffer);
            Map<String, byte[]> bufferMap = new HashMap<>();
            bufferMap.put("data", buffer);
            DecodeResult decodeResult;
            List<Object> returnObjs = new ArrayList<>();
            boolean rightDecoder = false;
            try {
                if (bufferMap.get("data").length <= 39) {//小于45
                    decodeResult = new DecodeResult(false, false);
                } else {
                    byte[] tmpHeadFlag = new byte[]{(bufferMap.get("data"))[0], (bufferMap.get("data"))[1]};
                    if (tmpHeadFlag[0] == PacketHead.FLAG[0] && tmpHeadFlag[1] == PacketHead.FLAG[1]) {//非设备命令
                        ByteBuffer byteBuffer = ByteBuffer.wrap(bufferMap.get("data")).asReadOnlyBuffer();
                        short packetLength = byteBuffer.getShort(10);
                        byte[] partData;
                        if (byteBuffer.remaining() < packetLength) {
                            if (packetLength >= 10000) {
                                log.error("来自" + ctx.channel().remoteAddress().toString() + "的非法数据包.");
                                decodeResult = new DecodeResult(false, false);
                            } else {
                                byteBuffer.mark();
                                partData = new byte[byteBuffer.remaining()];
                                byteBuffer.get(partData);
                                byteBuffer.reset();
                                String warnMsg = ctx.channel().remoteAddress().toString() + ":对于数据[" + ByteConventerKit.bytesToHexStr(partData, false) + "]长度不够一个包(需要的包长:" + packetLength + ",实际包长:" + byteBuffer.remaining() + ")，下一周期处理";
                                log.warn(warnMsg);
                                decodeResult = new DecodeResult(false, true);
                            }
                        } else {
                            partData = new byte[packetLength];
                            byteBuffer.get(partData, 0, partData.length);
                            Packet packet = Packet.deserialize(partData);
                            if (packet != null) {
                                PacketTail tail = packet.getTail();
                                if (tail == null) {
                                    returnObjs.add(packet);
                                } else if (tail.getSignature()) {
                                    returnObjs.add(packet);
                                } else {
                                    if ((byte) 0x21 == packet.getBody().getBusinessCmd().getCmdTypeValue()) {
                                        Report_IPhone catParam = new Report_IPhone();
                                        //IP话筒停播
                                        catParam.setBackCode(7);
                                        String[] getTargetCodes = packet.getBody().getTargetCodes();
                                        String logicalAddr = packet.getBody().getSourceCode();
                                        int sessionId = packet.getHead().getSessionId();
                                        Packet rebackPacket = new Packet();
                                        String sourceCode = "F00000000000000000000000";
                                        if (getTargetCodes != null && getTargetCodes.length > 0) {
                                            sourceCode = getTargetCodes[0];
                                        }
                                        PacketBody rebackBody = new PacketBody(sourceCode, new String[]{logicalAddr}, catParam);
                                        rebackPacket.setBody(rebackBody);
                                        boolean isSign = false;
                                        short rebackPacketLength = (short) (12 + rebackBody.serialize().length + PacketTail.getLength(isSign));
                                        PacketHead head = new PacketHead(sessionId, PacketHead.PacketType.RESPONSE, isSign, rebackPacketLength);
                                        packet.setHead(head);
                                        PacketTail rebackTail = new PacketTail(isSign, packet);
                                        rebackPacket.setTail(rebackTail);
                                        log.error("IP话筒喊话验签失败!");
                                        ctx.channel().writeAndFlush(packet);
                                    } else {
                                        returnObjs.add(packet);
                                    }
                                }
                            }

                            if (byteBuffer.hasRemaining()) {
                                byte[] remainData = new byte[byteBuffer.remaining()];
                                byteBuffer.get(remainData);
                                bufferMap.put("data", remainData);
                                ByteBuf buf = Unpooled.wrappedBuffer(remainData);
                                this.decode(ctx, buf, returnObjs);
                            } else {
                                bufferMap.remove("data");
                            }

                            decodeResult = new DecodeResult(true, true);
                        }
                    } else {
                        decodeResult = new DecodeResult(false, false);
                    }
                }

                if (!decodeResult.isSuccess()) {
                    rightDecoder = decodeResult.isRightDecoder();
                }
            } catch (Exception var12) {
                String msg = "对" + ctx.channel().remoteAddress().toString() + "发来的数据[" + ByteConventerKit.bytesToHexStr(buffer, false) + "]解析时发生错误.";
                log.error(msg, var12);
            }
            if (!returnObjs.isEmpty()) {
                list.addAll(returnObjs);
            }
            if (rightDecoder && bufferMap.containsKey("data") && bufferMap.get("data").length > 0) {
                int readerIndex = buffer.length - bufferMap.get("data").length;
                if (readerIndex >= 0) {
                    in.readerIndex(readerIndex);
                }
            }
        } catch (Exception e) {
            log.error("附录B解析异常：" + Arrays.toString(e.getStackTrace()));
            throw e;
        }
    }
}
